﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "GbmpModel.h"
#include "GbmpDefines.h"
#include "OwnerPtr.h"
#include "WeakPtr.h"
#include "ElementId.h"
#include "IElementShapeHandle.h"
#include "IElementViewSpecificShapeComponent.h"
#include "IElementShapeHandleBehavior.h"
#include "IElementUiManipulatorComponent.h"
#include "IElementTransformationComponent.h"
#include "IElementCopyPasteComponent.h"
#include "IElementRegenerationComponent.h"
#include "GbmpQuickCast.h"
#include "DbDataSchema.h"
#include "IElementParametersCustomizer.h"
#include "IParameterOverride.h"
#include "NdbObjectSchematic.h"
#include "ModelViewSymbolNewParameterOverrideBase.h"

namespace gcmp
{
    class IElement;
    class IGraphicsElementShape;
    class IModelView;
    class IGraphicsElementShape;
    class IDocument;
    class IElementParentReporter;
    class IElementParametersCustomizer;
    class ElementViewSpecificShapeComponent;

    // 立面标志夹点位置更新行为
    class GBMP_MODEL_EXPORT ElevationViewSymbolNewGripPointBehavior :public NdbObjectSchematic, public IElementShapeHandleBehavior
    {
        DBOBJECT_DATA_BEGIN_AND_QUICK_CAST_FROM(gcmp, ElevationViewSymbolNewGripPointBehavior, gcmp::NdbObjectSchematic, 01BEAB30 - 78E2 - 4EE5 - 96F6 - 2B91988181B7, gbmpmodel, gcmp::IElementShapeHandleBehavior)
            DATA(IDocument*, Document)
            DATA(ElementId, ModelViewId)    //表示这个夹点在哪个视图上显示的(切换视图夹点会刷新)
            DATA(ElementId, ElementShapeHandleId)
            DBOBJECT_DATA_END

    public:
        static OwnerPtr<IElementShapeHandleBehavior> Create(IDocument* pDoc, const ElementId& modelViewId);
        virtual ~ElevationViewSymbolNewGripPointBehavior() {}

    public:
        virtual IDocument* GetDocument() const override { return GetDocument__(); }
        void SetDocument(const IDocument* pDoc) { SetDocument__(pDoc); }

        virtual ElementId GetModelViewId() const override { return GetModelViewId__(); }
        void SetModelViewId(const ElementId &modelViewId) { SetModelViewId__(modelViewId); }

        virtual ElementId GetElementShapeHandleId() const override { return GetElementShapeHandleId__(); }
        virtual void SetElementShapeHandleId(const ElementId& id) override { return SetElementShapeHandleId__(id); }

        virtual void GetCalculators(ICalculatorCollection* calculators) const override;
        virtual bool Translate(const IElementMoveContext & moveContext) override;

        virtual OwnerPtr<IGraphicsElementShape> CreateGrahicsElementShapeInModelView(const IModelView* pModelView) const override;
        virtual void ReportParents(IElementParentReporter& reporter) const override;

        virtual void UpdatePosition() override;
        virtual void UpdatePositionIndexInMasterElement() override {};

        virtual void GetNearestPoint(Vector3d& nearPoint) const override;

        virtual bool FinishEditing() override { return false; }
        virtual bool GetHandleCommandString(const IObject* commandEnvironment, std::wstring& commandStr, CommandParameters& cmdParams) const override;

    public: //实现NdbObject接口
        virtual NdbObject* GetTopOwnerObject() const override
        {
            return nullptr;
        }

    private:
        ElevationViewSymbolNewGripPointBehavior(IDocument* pDoc, const ElementId& modelViewId);
        IElementShapeHandle* GetElementShapeHandle() const;
        IElement * GetMasterElement() const;
    };

    // 立面标志切割线位置更新行为
    class GBMP_MODEL_EXPORT ElevationViewSymbolNewBorderBehavior :public NdbObjectSchematic, public IElementShapeHandleBehavior
    {
        DBOBJECT_DATA_BEGIN_AND_QUICK_CAST_FROM(gcmp, ElevationViewSymbolNewBorderBehavior, gcmp::NdbObjectSchematic, F482BAB2 - DFA2 - 4D6A - 9882 - 098428A3181B, gbmpmodel, gcmp::IElementShapeHandleBehavior)
            DATA(IDocument*, Document)
            DATA(ElementId, ModelViewId)    //表示这个夹点在哪个视图上显示的(切换视图夹点会刷新)
            DATA(ElementId, ElementShapeHandleId)
            DBOBJECT_DATA_END

    public:
        static OwnerPtr<IElementShapeHandleBehavior> Create(IDocument* pDoc, const ElementId& modelViewId);
        virtual ~ElevationViewSymbolNewBorderBehavior() {}

    public:
        virtual IDocument* GetDocument() const override { return GetDocument__(); }
        void SetDocument(const IDocument* pDoc) { SetDocument__(pDoc); }

        virtual ElementId GetModelViewId() const override { return GetModelViewId__(); }
        void SetModelViewId(const ElementId &modelViewId) { SetModelViewId__(modelViewId); }

        virtual ElementId GetElementShapeHandleId() const override { return GetElementShapeHandleId__(); }
        virtual void SetElementShapeHandleId(const ElementId& id) override { return SetElementShapeHandleId__(id); }

        virtual void GetCalculators(ICalculatorCollection* calculators) const override;
        virtual bool Translate(const IElementMoveContext & moveContext) override;

        virtual OwnerPtr<IGraphicsElementShape> CreateGrahicsElementShapeInModelView(const IModelView* pModelView) const override;
        virtual void ReportParents(IElementParentReporter& reporter) const override;

        virtual void UpdatePosition() override;
        virtual void UpdatePositionIndexInMasterElement() override {};

        virtual void GetNearestPoint(Vector3d& nearPoint) const override;

        virtual bool FinishEditing() override { return false; }
        virtual bool GetHandleCommandString(const IObject* commandEnvironment, std::wstring& commandStr, CommandParameters& cmdParams) const override;

    public: //实现NdbObject接口
        virtual NdbObject* GetTopOwnerObject() const override
        {
            return nullptr;
        }

    private:
        ElevationViewSymbolNewBorderBehavior(IDocument* pDoc, const ElementId& modelViewId);
        IElementShapeHandle* GetElementShapeHandle() const;
        IElement * GetMasterElement() const;
    };

    // 立面标志辅助对象类型
    enum class ElevationViewSymbolNewAuxiliaryType : int8_t
    {
        None = 0,
        HorizontalStart = 1, // 水平向起点
        HorizontalEnd = 2,  // 水平向终点
        Border = 3 //水平裁剪线
    };

    // 立面标志视图相关行为
    class ElevationViewSymbolNewViewSpecificShapeComponent : public NdbObjectSchematic,
        public IElementViewSpecificShapeComponent
    {
        DBOBJECT_DATA_BEGIN_AND_QUICK_CAST_FROM(gcmp, ElevationViewSymbolNewViewSpecificShapeComponent, gcmp::NdbObjectSchematic, 5ECA50FC - 90E1 - 4B02 - 9FE6 - EAD65D23FBCE, gbmpmodel, IElementViewSpecificShapeComponent)
            DATA(OwnerPtr<IRenderPriorityOffsetProvider>, RenderPriorityOffsetProvider)
            DATA_TRANSIENT(IElement*, pOwnerElement)
            DATA(OwnerPtr<IGraphicsNodeVisibilityCustomizer>, GraphicsNodeVisibilityCustomizer)
        DBOBJECT_DATA_END
    public:
        virtual ~ElevationViewSymbolNewViewSpecificShapeComponent() {}

        virtual bool SetOwnerElement(IElement* pOwnerElement) override;
        virtual IElement* GetOwnerElement() override { return m_pOwnerElement; }
        virtual const IElement* GetOwnerElement() const override { return m_pOwnerElement; }
    public: //实现NdbObject接口
        virtual NdbObject* GetTopOwnerObject() const override
        {
            return nullptr;
        }

    public:
        virtual bool IsVisibleInModelView(const IModelView* pModelView) const override;
        virtual OwnerPtr<IGraphicsElementShape> CreateViewSpecificElementShape(const IModelView* pModelView) const override;
        virtual bool IsCuttableByModelViewRange(const IModelView* pModelView) const override { return false; }
        virtual void ReportDependentElements(std::vector<ElementId>& dependentElementIds) const override {};

        virtual void SetRenderPriorityOffsetProvider(OwnerPtr<IRenderPriorityOffsetProvider> opProvider) override;
        virtual const IRenderPriorityOffsetProvider* GetRenderPriorityOffsetProvider() const override;
        virtual IRenderPriorityOffsetProvider* GetRenderPriorityOffsetProvider() override;

        virtual void SetGraphicsNodeVisibilityCustomizer(OwnerPtr<IGraphicsNodeVisibilityCustomizer> opCustomizer) override;
        virtual const IGraphicsNodeVisibilityCustomizer* GetGraphicsNodeVisibilityCustomizer() const override;
        virtual IGraphicsNodeVisibilityCustomizer* GetGraphicsNodeVisibilityCustomizer() override;
    };

    // 立面标志UI操纵器组件
    class ElevationViewSymbolNewUiManipulatorComponent : public NdbObjectSchematic, public IElementUiManipulatorComponent
    {
        DBOBJECT_DATA_BEGIN_AND_QUICK_CAST_FROM(gcmp, ElevationViewSymbolNewUiManipulatorComponent, gcmp::NdbObjectSchematic, 39C34FFD - 14DE - 4DAE - A826 - E0F8F281A39A, gbmpmodel, IElementUiManipulatorComponent)
        DBOBJECT_DATA_END
    public:
        virtual bool SetOwnerElement(IElement* pOwnerElement) override { m_pOwnerElement = pOwnerElement; return true; }
        virtual IElement* GetOwnerElement() override { return m_pOwnerElement; }
        virtual const IElement* GetOwnerElement() const override { return m_pOwnerElement; }

    public: //实现NdbObject接口
        virtual NdbObject* GetTopOwnerObject() const override
        {
            return nullptr;
        }

    private:
        ElementId CreateGripPoint(ElevationViewSymbolNewAuxiliaryType type, const gcmp::ElementId& modelviewId) const;
        ElementId CreateBorder(const gcmp::ElementId& modelviewId) const;

    private:
        IElement* m_pOwnerElement;
    };

    // 立面标志移动、旋转行为
    class ElevationViewSymbolNewTransformationComponent :public NdbObjectSchematic, public IElementTransformationComponent
    {
        DBOBJECT_DATA_BEGIN(gcmp, ElevationViewSymbolNewTransformationComponent, gcmp::NdbObjectSchematic, B2A08A3C - 3F53 - 4CD8 - A3F5 - E5C159F31DCD, gbmpmodel)
        DBOBJECT_DATA_END
    public:
        virtual bool SetOwnerElement(IElement* pOwnerElement) override { m_pOwnerElement = pOwnerElement; return true; }
        virtual IElement* GetOwnerElement() override { return m_pOwnerElement; }
        virtual const IElement* GetOwnerElement() const override { return m_pOwnerElement; }

        virtual bool CanBeMoved(std::wstring* explanation = nullptr) const override;
        virtual bool Translate(const IElementMoveContext& moveContext) override;

        virtual bool CanBeRotated(std::wstring* explanation = nullptr) const override { return false; }
        virtual bool Rotate(const Vector3d& pointOnVec, const Vector3d& rotateDir, double rotateAngle) override { return false; }

        virtual bool CanBeScaled(std::wstring* explanation = nullptr) const override { return false; }
        virtual bool Scale(const Vector3d& basePt, float scaleFactor) override { return false; }

        virtual bool Transform(const Matrix4d& matrix) override;
    public: //实现NdbObject接口
        virtual NdbObject* GetTopOwnerObject() const override
        {
            return nullptr;
        }
    private:
        IElement* m_pOwnerElement;
    };

    // 立面标志参数行为
    class ElevationViewSymbolNewParametersCustomizer : public NdbObjectSchematic, public IElementParametersCustomizer
    {
        DBOBJECT_DATA_BEGIN_AND_QUICK_CAST_FROM(gcmp, ElevationViewSymbolNewParametersCustomizer, gcmp::NdbObjectSchematic, D8C52ED6-3855-4D15-A920-82F2D2314993, gbmpmodel, IElementParametersCustomizer)
        DBOBJECT_DATA_END
    public:
        ElevationViewSymbolNewParametersCustomizer(const IElement* pElement) :m_pOwnerElement(pElement) {};

        virtual OwnerPtr<IParameter> GetNativeParameter(int paramDefId) const override;
        virtual bool SetNativeParameter(const IParameter *param, std::wstring* errorMsg) override;
        virtual void ReportParameterDefinitions(std::vector<int>* pParamDefIds) const override;
        virtual bool IsParameterModifiable(int parameterId) const override;
        virtual bool IsPresetParameter(const UniIdentity& paramDefUid) const override { return true; }
        virtual void FilterParameterValues(const UniIdentity& paramDefUid, 
            std::vector<OwnerPtr<IParameterValueStorage>>& values) const override {}

    public:
        virtual bool SetOwnerElement(IElement* pOwnerElement) override { m_pOwnerElement = pOwnerElement; return true; }
        virtual IElement* GetOwnerElement() override { return m_pOwnerElement.Get(); }
        virtual const IElement* GetOwnerElement() const override { return m_pOwnerElement.Get(); }
    public: //实现NdbObject接口
        virtual NdbObject* GetTopOwnerObject() const override
        {
            return nullptr;
        }
    private:
        const IElementParameters* GetElevationModelViewParameters() const;
        IElementParameters* GetElevationModelViewParameters();
    private:
        WeakPtr<IElement> m_pOwnerElement;
    };

    // 立面视图标记名字参数定制
    class ElevationViewSymbolNewNameParameterOverride : public NdbObjectSchematic, public ModelViewSymbolNewParameterOverrideBase
    {
        DBOBJECT_DATA_BEGIN_AND_QUICK_CAST_FROM(gcmp, ElevationViewSymbolNewNameParameterOverride, gcmp::NdbObjectSchematic, 345FD7AF - 3A5E - 4879 - A2A0 - A0ED27200BC2, gbmpmodel, gcmp::IParameterOverride)
            DATA_TRANSIENT(IElement*, pOwnerElement)
            DBOBJECT_DATA_END

    public:
        ElevationViewSymbolNewNameParameterOverride(IElement* pElement) :m_pOwnerElement(pElement) {};

        DECLARE_MODEL_VIEW_SYMBOL_NEW_PARAMETER_OVERRID_METHODS

    public: //实现NdbObject接口
        virtual NdbObject* GetTopOwnerObject() const override
        {
            return nullptr;
        }

    private:
        virtual const UniIdentity& GetUidForParameterOverride() const override;
    };

    //Regeneration Behavior
    class ElevationViewSymbolNewRegenerationBehavior :public NdbObjectSchematic, public IElementRegenerationComponent
    {
        DBOBJECT_DATA_BEGIN_AND_QUICK_CAST_FROM(gcmp, ElevationViewSymbolNewRegenerationBehavior, gcmp::NdbObjectSchematic, 720871A7 - A629 - 4C0B - AD53 - 0CCAF13B4670, gbmpmodel, IElementRegenerationComponent)
        DBOBJECT_DATA_END
    public:
        virtual bool SetOwnerElement(IElement* pOwnerElement) override;
        virtual const IElement* GetOwnerElement() const override { return m_opOwnerElement; }
        virtual IElement* GetOwnerElement() override { return m_opOwnerElement; }
    public: //实现NdbObject接口
        virtual NdbObject* GetTopOwnerObject() const override
        {
            return nullptr;
        }
       
    public:
        ElevationViewSymbolNewRegenerationBehavior(IElement* pElement);

        virtual bool CanHaveRegenData() const override;

        virtual bool CanHaveCalculators() const override;

        virtual void GetCalculators(ICalculatorCollection* calculators) const override;
        
    private:
        IDocument* GetDocument() const;

    private:
        IElement* m_opOwnerElement;
        OwnerPtr<IElementRegenerationComponent> m_ElementRegenerationBehavior;
    };
}
